﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Specialized;
using Beetle.Web.Composite;
using System.Collections;
using Beetle.Web.UI.WebControls;

namespace Beetle.Web.Extensions
{
    /// <summary>
    /// Control类扩展
    /// </summary>
    /// <!-- 作者:韦腾  时间:2010年03月26日 -->
    public static class ControlExtension
    {
        /// <summary>
        /// 获取控件树第一个有效DataItemContainer
        /// </summary>
        /// <param name="control"></param>
        /// <returns>object</returns>
        public static object GetDataItem(this Control control)
        {
            Control ctrl = control;
            IDataItemContainer container = null;
            while (ctrl != null && ctrl.GetType() != typeof(System.Web.UI.Page))
            {
                container = ctrl as IDataItemContainer;
                if (container != null)
                {
                    if (container.DataItem != null)
                    {
                        return container;
                    }
                }

                ctrl = ctrl.Parent;
            }

            return null;
        }

        /// <summary>
        ///  通过类来实现时，使用模板化内容中的双向 ASP.NET 数据绑定语法对绑定值的一组名称/值对进行检索。
        /// </summary>
        /// <param name="container">在双向数据绑定方案中，数据绑定控件将 System.Web.UI.Control（要从中提取名称/值对）传递至关联的数据源控件</param>
        /// <returns> 名称/值对的 System.Collections.Specialized.IOrderedDictionary。名称表示模板化内容中控件的名称，值是使用双向ASP.NET 数据绑定语法绑定的属性值的当前值。</returns>
        public static IOrderedDictionary ExtractValues(this Control container)
        {
            OrderedDictionary dictionary = new OrderedDictionary();

            Type containerType = container.GetType();
            System.Reflection.PropertyInfo propertyInfo = containerType.GetProperty("Extensions");
            if (propertyInfo != null)
            {
                Type collectionType = typeof(ICollection);
                object propertyValue = propertyInfo.GetValue(container, null);
                bool isCollection = collectionType.IsInstanceOfType(propertyValue);

                if (isCollection)
                {
                    ICollection extCollection = propertyValue as ICollection;

                    if (extCollection != null)
                    {
                        foreach (object ext in extCollection)
                        {
                            TowWayBindExtension towwayExt = ext as TowWayBindExtension;

                            if (towwayExt != null && towwayExt.CanExtract && !string.IsNullOrEmpty(towwayExt.Property) && !string.IsNullOrEmpty(towwayExt.Expression))
                            {
                                if (!dictionary.Contains(towwayExt.Expression))
                                {
                                    object value = DataBinder.Eval(container, towwayExt.Property);

                                    if (value != null)
                                    {
                                        dictionary.Add(towwayExt.Expression, value);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            IOrderedDictionary dictionarySub = null;
            foreach (Control subcontrol in container.Controls)
            {
                dictionarySub = subcontrol.ExtractValues();

                foreach (System.Collections.DictionaryEntry entry in dictionarySub)
                {
                    if (!dictionary.Contains(entry.Key))
                    {
                        dictionary.Add(entry.Key, entry.Value);
                    }
                }
            }

            dictionarySub = null;

            return dictionary;
        }

        /// <summary>
        /// 获取子控件
        /// </summary>
        /// <typeparam name="T">子控件类型</typeparam>
        /// <typeparam name="E">拥有的</typeparam>
        /// <param name="container"></param>
        /// <returns></returns>
        public static List<T> FindAllControls<T, E>(this Control container)
            where T : System.Web.UI.Control
            where E : ExtensionBase
        {
            List<T> controls = container.FindAllControls<T>();
            List<T> returnControls = new List<T>();

            foreach (T ctrl in controls)
            {
                Type containerType = ctrl.GetType();
                System.Reflection.PropertyInfo propertyInfo = containerType.GetProperty("Extensions");
                if (propertyInfo != null)
                {
                    Type collectionType = typeof(ICollection);
                    object propertyValue = propertyInfo.GetValue(ctrl, null);
                    bool isCollection = collectionType.IsInstanceOfType(propertyValue);

                    if (isCollection)
                    {
                        ICollection extCollection = propertyValue as ICollection;

                        if (extCollection != null)
                        {
                            foreach (object ext in extCollection)
                            {
                                if (null != (ext as E))
                                {
                                    returnControls.Add(ctrl);
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            return returnControls;
        }

        /// <summary>
        /// 获取控件是否是编辑状态
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        public static bool GetEditMode(this Control control)
        {
            while (control != null && control.GetType() != typeof(System.Web.UI.Page))
            {
                IEditStatus editStatusControl = control as IEditStatus;

                if (editStatusControl != null)
                {
                    if (editStatusControl.InternalEditMode != null)
                    {
                        editStatusControl.SetInternalEditModeValue(editStatusControl.InternalEditMode.Value);
                        return editStatusControl.InternalEditMode.Value;
                    }
                    else if (!editStatusControl.IsEditMode)
                    {
                        editStatusControl.SetInternalEditModeValue(false);
                        return false;
                    }
                }

                control = control.Parent;
            }

            return true;
        }

        /// <summary>
        /// 重置编辑模式
        /// </summary>
        /// <param name="control"></param>
        public static void ResetEditMode(this Control control)
        {
            while (control != null && control.GetType() != typeof(System.Web.UI.Page))
            {
                IEditStatus editStatusControl = control as IEditStatus;

                if (editStatusControl != null)
                {
                    editStatusControl.SetInternalEditModeValue(null);
                }

                control = control.Parent;
            }
        }

        /// <summary>
        /// 搜索特定类型的子控件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="control"></param>
        /// <returns></returns>
        public static List<T> FindAllControls<T>(this System.Web.UI.Control control)
          where T : System.Web.UI.Control
        {
            List<T> list = new List<T>();
            Type findType = typeof(T);

            foreach (Control subControl in control.Controls)
            {
                if (subControl.GetType() == findType || subControl.GetType().IsSubclassOf(findType))
                {
                    list.Add(subControl as T);
                }

                list.AddRange(subControl.FindAllControls<T>());
            }

            return list;
        }

        /// <summary>
        ///  搜索特定类型的子控件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="control"></param>
        /// <param name="findTypes"></param>
        /// <returns></returns>
        public static List<T> FindAllControls<T>(this System.Web.UI.Control control, params Type[] findTypes)
            where T : System.Web.UI.Control
        {
            List<T> list = new List<T>();

            foreach (Control subControl in control.Controls)
            {
                if (ControlExtension.IsContainerType(findTypes, subControl.GetType()))
                {
                    list.Add(subControl as T);
                }

                list.AddRange(subControl.FindAllControls<T>(findTypes));
            }

            return list;
        }

        private static bool IsContainerType(Type[] findTypes, Type type)
        {
            foreach (Type item in findTypes)
            {
                if (type == item || item.IsSubclassOf(type))
                {
                    return true;
                }
            }

            return false;
        }
    }
}
